/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  							 terrain.h

	$Header: /heroes4/terrain.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( TERRAIN_H_INCLUDED )
#define TERRAIN_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <cassert>
#include <string>

// ---------------------------------------------------------------
// enum for terrain types
// ---------------------------------------------------------------
enum t_terrain_type
{
	k_terrain_water,
	k_terrain_grass,
	k_terrain_rough,
	k_terrain_swamp,
	k_terrain_lava,
	k_terrain_snow,
	k_terrain_sand,
	k_terrain_dirt,
	k_terrain_subterranean,
	k_terrain_water_river,
	k_terrain_lava_river,
	k_terrain_ice_river,
	k_terrain_magic_all,
	k_terrain_magic_life,
	k_terrain_magic_order,
	k_terrain_magic_death,
	k_terrain_magic_chaos,
	k_terrain_magic_nature,
	k_terrain_might,

	k_terrain_count,

	k_basic_terrain_count = k_terrain_subterranean + 1
};

int const k_terrain_subtype_max = 2;

int const k_terrain_water_subtype_count = 2;
int const k_terrain_grass_subtype_count = 2;
int const k_terrain_rough_subtype_count = 2;
int const k_terrain_swamp_subtype_count = 2;
int const k_terrain_lava_subtype_count = 2;
int const k_terrain_snow_subtype_count = 2;
int const k_terrain_sand_subtype_count = 2;
int const k_terrain_dirt_subtype_count = 2;
int const k_terrain_subterranean_subtype_count = 2;
int const k_terrain_water_river_subtype_count = 1;
int const k_terrain_lava_river_subtype_count = 1;
int const k_terrain_ice_river_subtype_count = 1;
int const k_terrain_magic_all_subtype_count = 1;
int const k_terrain_magic_life_subtype_count = 1;
int const k_terrain_magic_order_subtype_count = 1;
int const k_terrain_magic_death_subtype_count = 1;
int const k_terrain_magic_chaos_subtype_count = 1;
int const k_terrain_magic_nature_subtype_count = 1;
int const k_terrain_might_subtype_count = 1;

inline int get_terrain_subtype_count( t_terrain_type terrain )
{
	assert( terrain >= 0 && terrain < k_terrain_count );

	static int const k_subtype_count_array[ k_terrain_count ] =
	{
		k_terrain_water_subtype_count,
		k_terrain_grass_subtype_count,
		k_terrain_rough_subtype_count,
		k_terrain_swamp_subtype_count,
		k_terrain_lava_subtype_count,
		k_terrain_snow_subtype_count,
		k_terrain_sand_subtype_count,
		k_terrain_dirt_subtype_count,
		k_terrain_subterranean_subtype_count,
		k_terrain_water_river_subtype_count,
		k_terrain_lava_river_subtype_count,
		k_terrain_ice_river_subtype_count,
		k_terrain_magic_all_subtype_count,
		k_terrain_magic_life_subtype_count,
		k_terrain_magic_order_subtype_count,
		k_terrain_magic_death_subtype_count,
		k_terrain_magic_chaos_subtype_count,
		k_terrain_magic_nature_subtype_count,
		k_terrain_might_subtype_count,
	};

	return k_subtype_count_array[ terrain ];
}

std::string const & get_terrain_type_name( t_terrain_type type, int subtype );
std::string const & get_terrain_type_description( t_terrain_type type, int subtype );

t_terrain_type get_basic_terrain( t_terrain_type type );
t_terrain_type get_terrain_type( std::string const& keyword );

inline bool is_flat_terrain( t_terrain_type type )
{
	assert( type >= 0 && type < k_terrain_count );
	return type == k_terrain_water || type == k_terrain_swamp;
}

inline bool is_water_terrain( t_terrain_type type )
{
	assert( type >= 0 && type < k_terrain_count );
	return	type == k_terrain_water || 
			type == k_terrain_water_river || 
			type == k_terrain_lava_river ||
			type == k_terrain_ice_river;
}

extern char const * const k_terrain_keyword[ k_terrain_count ];

// ---------------------------------------------------------------
// enum for road types
// ---------------------------------------------------------------

enum t_road_type
{
	k_road_none,
	k_road_stone,
	k_road_dirt,
	k_road_cobbles,

	k_road_type_count,
};

std::string const & get_road_type_name( t_road_type type );
std::string const & get_road_type_description( t_road_type type );

// ---------------------------------------------------------------
// enum for rock terrain types
// ---------------------------------------------------------------

enum t_rock_terrain_type
{
	k_rock_terrain_none,
	k_rock_terrain_cave,
	k_rock_terrain_stone,

	k_rock_terrain_type_count,
};

std::string const & get_rock_terrain_type_name( t_rock_terrain_type type );
std::string const & get_rock_terrain_type_description( t_rock_terrain_type type );

// ---------------------------------------------------------------
// previous enum for terrain types
// ---------------------------------------------------------------
enum t_old_terrain_type
{
	k_old_terrain_water,
	k_old_terrain_grass,
	k_old_terrain_rough,
	k_old_terrain_swamp,
	k_old_terrain_lava,
	k_old_terrain_snow,
	k_old_terrain_sand,
	k_old_terrain_dirt,
	k_old_terrain_water_river,
	k_old_terrain_lava_river,
	k_old_terrain_ice_river,
	k_old_terrain_magic_all,
	k_old_terrain_magic_life,
	k_old_terrain_magic_order,
	k_old_terrain_magic_death,
	k_old_terrain_magic_chaos,
	k_old_terrain_magic_nature,
	k_old_terrain_personal_combat,
	k_old_terrain_tactical,

	k_old_terrain_count
};

inline t_terrain_type translate( t_old_terrain_type old_type )
{
	assert( old_type >= 0 && old_type < k_old_terrain_count );

	static t_terrain_type const k_old_to_new_map[ k_old_terrain_count ] =
	{
		k_terrain_water,
		k_terrain_grass,
		k_terrain_rough,
		k_terrain_swamp,
		k_terrain_lava,
		k_terrain_snow,
		k_terrain_sand,
		k_terrain_dirt,
		k_terrain_water_river,
		k_terrain_lava_river,
		k_terrain_ice_river,
		k_terrain_magic_all,
		k_terrain_magic_life,
		k_terrain_magic_order,
		k_terrain_magic_death,
		k_terrain_magic_chaos,
		k_terrain_magic_nature,
		k_terrain_might,
		k_terrain_might,
	};

	return k_old_to_new_map[ old_type ];
}

// -------------------------------------------------------------------------------
// t_full_terrain_type class
// -------------------------------------------------------------------------------

class t_full_terrain_type
{
public:
	// Constructors
	t_full_terrain_type() {}
	t_full_terrain_type( t_terrain_type type, int subtype );

	// Member functions
	void			assign( t_terrain_type new_type, int new_subtype );
	int				get_subtype() const;
	t_terrain_type	get_type() const;
	
	// Operator
	operator t_terrain_type() const;

private:
	// Data members
	t_terrain_type	m_type;
	int				m_subtype;
};

inline t_full_terrain_type::t_full_terrain_type( t_terrain_type type, int subtype )
	:	m_type( type ),
		m_subtype( subtype )
{
	assert( m_type >= 0 && m_type < k_terrain_count );
	assert( m_subtype >= 0 && m_subtype < get_terrain_subtype_count( m_type ) );
}

inline void t_full_terrain_type::assign( t_terrain_type new_type, int new_subtype )
{
	assert( new_type >= 0 && new_type < k_terrain_count );
	assert( new_subtype >= 0 && new_subtype < get_terrain_subtype_count( new_type ) );
	m_type = new_type;
	m_subtype = new_subtype;
}

inline int t_full_terrain_type::get_subtype() const
{
	return m_subtype;
}

inline t_terrain_type t_full_terrain_type::get_type() const
{
	return m_type;
}

inline t_full_terrain_type::operator t_terrain_type() const
{
	return m_type;
}

inline bool operator==( t_full_terrain_type const & left, t_full_terrain_type const & right )
{
	return left.get_type() == right.get_type() && left.get_subtype() == right.get_subtype();
}

inline bool operator!=( t_full_terrain_type const & left, t_full_terrain_type const & right )
{
	return !( left == right );
}

#endif // !defined( TERRAIN_H_INCLUDED )
